/*
 * Copyright (C) 2016, apexes.net. All rights reserved.
 * 
 *        http://www.apexes.net
 * 
 */
package net.apexes.wsonrpc.demo.server;

import net.apexes.wsonrpc.core.RemoteInvoker;
import net.apexes.wsonrpc.core.WsonrpcRemote;
import net.apexes.wsonrpc.demo.api.PushService;
import net.apexes.wsonrpc.server.WsonrpcRemotes;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.UUID;

/**
 * 
 * @author <a href="mailto:hedyn@foxmail.com">HeDYn</a>
 *
 */
public abstract class AbstractDemoWsonrpcServer implements DemoServer {
    private static final Logger LOG = LoggerFactory.getLogger(AbstractDemoWsonrpcServer.class);
    
    @Override
    public void ping(String clientId) {
        if (clientId == null) {
            for (WsonrpcRemote remote : WsonrpcRemotes.getRemotes()) {
                try {
                    ping(remote);
                } catch (Exception e) {
                    LOG.error("", e);
                }
            }
        } else {
            WsonrpcRemote remote = findRemote(clientId);
            try {
                ping(remote);
            } catch (Exception e) {
                LOG.error("", e);
            }
        }
    }

    private void ping(WsonrpcRemote remote) throws Exception {
        String text = "PingByServer" + System.currentTimeMillis();
        remote.ping(text.getBytes());
    }

    @Override
    public void call(String clientId) {
        if (clientId == null) {
            for (WsonrpcRemote remote : WsonrpcRemotes.getRemotes()) {
                call(remote);
            }
        } else {
            WsonrpcRemote remote = findRemote(clientId);
            call(remote);
        }
    }
    
    private void call(WsonrpcRemote remote) {
        if (remote != null) {
            PushService service = remoteService(remote, PushService.class);
            String callParam = UUID.randomUUID().toString();
            LOG.info("callParam={}", callParam);
            String callValue = service.setupStatus(callParam);
            LOG.info("callValue={}", callValue);
        }
    }

    private <T> T remoteService(WsonrpcRemote remote, Class<T> serviceClass) {
        return RemoteInvoker.create(remote)
                .simpleName()
                .trace(() -> String.valueOf(System.currentTimeMillis()))
                .get(serviceClass);
    }

    @Override
    public void notice(String message, String clientId) {
        LOG.info("notice {} {} ...", message, clientId);
        if (clientId == null) {
            for (WsonrpcRemote remote : WsonrpcRemotes.getRemotes()) {
                notice(remote, message);
            }
        } else {
            WsonrpcRemote remote = findRemote(clientId);
            notice(remote, message);
        }
    }
    
    private void notice(WsonrpcRemote remote, String message) {
        try {
            if (remote != null) {
                PushService service = remoteService(remote, PushService.class);
                service.notice(message);
            }
        } catch (Exception e) {
            LOG.error("notice error.", e);
        }
    }
    
    static WsonrpcRemote findRemote(String clientId) {
        String sessionId = DemoOnlineClientHolder.getSessionId(clientId);
        return WsonrpcRemotes.getRemote(sessionId);
    }

}
